package com.hatch.media
{
	import com.hatch.ui.Component;
	
	import flash.display.Loader;
	import flash.events.Event;
	import flash.events.StatusEvent;
	import flash.events.TimerEvent;
	import flash.net.LocalConnection;
	import flash.net.URLRequest;
	import flash.system.Security;
	import flash.utils.Timer;

	public class YTSkinlessPlayer extends Component
	{
		private var _loader:Loader; 
	 	private var _as3_to_as2:LocalConnection; 
	    private var _as2_to_as3:LocalConnection;
	
	 	private var _playerURL:String = "YTSkinlessWrap.swf"
	 	private var _loadAtInit:Boolean;
	 	private var _playerLoaded:Boolean;
	 	private var _queueVideoID:String;
	 	private var _updateTimer:Timer;
	 	private var _updateInterval:Number = 250;
	 	
	 	//PLAYER DATA
	 	private var _volume:Number;
	 	private var _videoBytesLoaded:Number = 0;
	 	private var _videoBytesTotal:Number = 0;
	 	private var _currentTime:Number = 0;
	 	private var _duration:Number = 0
	 	private var _videoUrl:String;
	 	private var _videoStartBytes:Number = 0;
	 	private var _isMuted:Boolean = false;
	 	private var _videoEmbedCode:String;
	 	private var _playerState:int = YTSkinlessPlayer.STATE_UNSTARTED;
	 	
	 	//constants
	 	public static const STATE_UNSTARTED:int = -1;
	 	public static const STATE_ENDED:int = 0;
	 	public static const STATE_PLAYING:int = 1;
	 	public static const STATE_PAUSED:int = 2;
	 	public static const STATE_BUFFERING:int = 3;
	 	public static const STATE_VIDEO_CUED:int = 5;
	 	
	 	//events
	 	public static const EVENT_PLAYER_LOADED:String = "playerlayerLoaded";
	 	public static const EVENT_VIDEO_PROGRESS:String = "playerProgress";
	 	public static const EVENT_LOAD_PROGRESS:String = "loadProgress";
	 	public static const EVENT_STATE_CHANGE:String = "stateChange";
	    
		public function YTSkinlessPlayer( playerURL:String, loadAtInit:Boolean = true )
		{
			_loadAtInit = loadAtInit;
			_playerURL = playerURL;
			super();
		}
		
		override protected function init():void
		{
			//security allowances
			Security.allowDomain('www.youtube.com'); 
			Security.allowDomain('gdata.youtube.com'); 
			Security.allowInsecureDomain('gdata.youtube.com'); 
			Security.allowInsecureDomain('www.youtube.com'); 
			
			_playerLoaded = false;
			
			super.init();
		}
		
		override protected function addChildren():void
		{
			_as3_to_as2 = new LocalConnection(); 
           	_as3_to_as2.addEventListener(StatusEvent.STATUS, onLocalConnectionStatusChange); 
           	_as2_to_as3 = new LocalConnection(); 
			_as2_to_as3.addEventListener(StatusEvent.STATUS, onLocalConnectionStatusChange); 
			_as2_to_as3.client = this; //This enables the local connection to use functions of this class 
			_as2_to_as3.connect("AS2_to_AS3");
           	_loader = new Loader();
           	
           	_updateTimer = new Timer(_updateInterval);
           	_updateTimer.addEventListener(TimerEvent.TIMER, onUpdateTimer);
           	
           	if(_loadAtInit) loadPlayer(); 	
		}
		
		override public function draw():void
		{
			_as3_to_as2.send("AS3_to_AS2", "setSize", this.width, this.height);
		}
		
		public function loadByID( id:String ):void
		{
			if(_playerLoaded)
			{
				_as3_to_as2.send("AS3_to_AS2", "loadVideoById", id);
				_updateTimer.start();
			}
			else
			{
				_queueVideoID = id;
				throw new Error ("Skinless player not loaded yet :: video will be played when player load completes");
			}
			
		}
		
		public function loadPlayer():void
		{
			_loader.load(new URLRequest(_playerURL));
		}
		
		public function stopVideo():void
       	{ 
       		_as3_to_as2.send("AS3_to_AS2", "stopVideo"); 
       		_updateTimer.reset();
		} 
		public function playVideo():void
		{ 
			_as3_to_as2.send("AS3_to_AS2", "playVideo");
			_updateTimer.start();
			
		} 
		public function pauseVideo():void
		{ 
        	_as3_to_as2.send("AS3_to_AS2", "pauseVideo"); 
        	_updateTimer.stop();
  		}
  		
  		public function mute():void
  		{
  			_as3_to_as2.send("AS3_to_AS2", "mute"); 
  		}
  		
  		public function unmute():void
  		{
  			_as3_to_as2.send("AS3_to_AS2", "unmute");
  		}
  		
  		public function seekTo(seconds:Number, allowSeekAhead:Boolean = false):void
  		{
  			_as3_to_as2.send("AS3_to_AS2", "seekTo", seconds, allowSeekAhead ); 
  		}		
		
		public function onSwfLoadComplete():void
		{
			_playerLoaded = true;
			addChild(_loader);
			dispatchEvent(new Event( YTSkinlessPlayer.EVENT_PLAYER_LOADED ) );
			if(_queueVideoID != "")
			{
				loadByID(_queueVideoID);
				_queueVideoID = "";
			}
		}
		
		private function onLocalConnectionStatusChange(e:StatusEvent):void
		{ 
			// error is thrown without this handler 
		}
		
		private function onUpdateTimer(event:TimerEvent):void
		{
			updatePlayerInfo();
		}
		
		private function updatePlayerInfo():void
		{
			updateVideoBytesLoaded();
			updateCurrentTime();
		}
		
		private function onVideoPlay():void
		{
			updateVideoBytesTotal();
			updateDuration();
			updateVolume();
		}
		
		public function updateVolume():void				{ _as3_to_as2.send("AS3_to_AS2", "getVolume"); }
		public function updateVideoBytesLoaded():void	{ _as3_to_as2.send("AS3_to_AS2", "getVideoBytesLoaded"); }
		public function updateVideoBytesTotal():void	{ _as3_to_as2.send("AS3_to_AS2", "getVideoBytesTotal"); }
		public function updateCurrentTime():void		{ _as3_to_as2.send("AS3_to_AS2", "getCurrentTime"); }
		public function updateDuration():void			{ _as3_to_as2.send("AS3_to_AS2", "getDuration"); }
		
		public function setVolume( value:* ):void
		{
			_volume = value;
			_as3_to_as2.send("AS3_to_AS2", "setVolume", value );
		}
		
		public function setVideoBytesLoaded( value:* ):void
		{
			//trace("BYTES LOADED = " + value);
			_videoBytesLoaded = value;
			dispatchEvent(new Event(YTSkinlessPlayer.EVENT_LOAD_PROGRESS));
		}
		
		public function setVideoBytesTotal( value:* ):void
		{
			//trace("BYTES TOTAL = " + value);
			_videoBytesTotal = value;
		}
		
		public function setCurrentTime( value:* ):void
		{
			//trace("CURRENT TIME = " + value);
			_currentTime = value;
			dispatchEvent(new Event(YTSkinlessPlayer.EVENT_VIDEO_PROGRESS));
		}
		
		public function setDuration( value:* ):void
		{
			//trace("DURATION = " + value);
			_duration = value;
		}
		
		public function setVideoUrl( value:* ):void
		{
			_videoUrl = value;
		}
		
		public function setVideoStartBytes( value:* ):void
		{
			_videoStartBytes = value;
		}
		
		public function setIsMuted( value:* ):void
		{
			_isMuted = value;
		}
		
		public function setVideoEmbedCode( value:* ):void
		{
			_videoEmbedCode = value;
		}
		
		public function setPlayerState( value:* ):void
		{
			switch(value)
			{
				case -1 :
					_playerState = YTSkinlessPlayer.STATE_UNSTARTED;
					trace("VID UNSTARTED");
					break;
				case 0 :
					_playerState = YTSkinlessPlayer.STATE_ENDED;
					break;
				case 1 :
					_playerState = YTSkinlessPlayer.STATE_PLAYING;
					trace("VID PLAYING");
					onVideoPlay();
					break;
				case 2 :
					_playerState = YTSkinlessPlayer.STATE_PAUSED;
					break;
				case 3 :
					_playerState = YTSkinlessPlayer.STATE_BUFFERING;
					trace("VID BUFFERING");
					break;	
				case 4 :
					_playerState = YTSkinlessPlayer.STATE_VIDEO_CUED;
					trace("VID CUED");
					break;				
			}
			dispatchEvent(new Event(YTSkinlessPlayer.EVENT_STATE_CHANGE));
		}
		
		public function get playerLoaded():Boolean{ return _playerLoaded; }
		public function get playerState():Number{ return _playerState; }
		public function get volume():Number{ return _volume; }
		public function get videoBytesLoaded():Number{ return _videoBytesLoaded; }
		public function get videoBytesTotal():Number { return _videoBytesTotal; }
		public function get currentTime():Number { return _currentTime; }
		public function get duration():Number { return _duration; }
		public function get videoURL():String { return _videoUrl; }
		public function get videoStartBytes():Number { return _videoStartBytes; }
		public function get isMuted():Boolean { return _isMuted; }
		public function get videoEmbedCode():String { return _videoEmbedCode; }
	}
}